﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Mathhammer40K
{
    public class ImperialRoller
    {
        Random randomNumberGenerator;

        public ImperialRoller()
        {
            randomNumberGenerator = new Random((int)DateTime.Now.Ticks & 0x0000FFFF);
            luckmodifier = 0;
        }

        Double luckmodifier;
        public Double LuckModifier
        {
            get { return luckmodifier; }
            set { luckmodifier = value; }
        }

        public class Distribution
        {
            Int64 totalOnes;
            Int32 ones;
            public Int32 Ones
            {
                get { return ones; }
            }
            Int64 totalTwos;
            Int32 twos;
            public Int32 Twos
            {
                get { return twos; }
            }
            Int64 totalThrees;
            Int32 threes;
            public Int32 Threes
            {
                get { return threes; }
            }
            Int64 totalFours;
            Int32 fours;
            public Int32 Fours
            {
                get { return fours; }
            }
            Int64 totalFives;
            Int32 fives;
            public Int32 Fives
            {
                get { return fives; }
            }
            Int64 totalSixes;
            Int32 sixes;
            public Int32 Sixes
            {
                get { return sixes; }
            }

            public Int32 TwoPlus
            {
                get { return twos + threes + fours + fives + sixes; }
            }

            public Int32 ThreePlus
            {
                get { return threes + fours + fives + sixes; }
            }

            public Int32 FourPlus
            {
                get { return fours + fives + sixes; }
            }

            public Int32 FivePlus
            {
                get { return fives + sixes; }
            }

            public Int32 SixPlus
            {
                get { return sixes; }
            }

            public Double Average
            {
                get { return (ones + twos * 2 + threes * 3 + fours * 4 + fives * 5 + sixes * 6) / ((Double)(ones + twos + threes + fours + fives + sixes)); }
            }

            public void AddRoll(UInt16 value)
            {
                switch (value)
                {
                    case 1:
                        ones++;
                        totalOnes++;
                        break;
                    case 2:
                        twos++;
                        totalTwos++;
                        break;
                    case 3:
                        threes++;
                        totalThrees++;
                        break;
                    case 4:
                        fours++;
                        totalFours++;
                        break;
                    case 5:
                        fives++;
                        totalFives++;
                        break;
                    case 6:
                        sixes++;
                        totalSixes++;
                        break;
                    default:
                        throw new Exception("AddRoll was given a value not in [1,6]");
                }

            }

        }

        public Distribution RollD6(Int32 rolls = 1)
        {
            Distribution result = new Distribution();

            for (int i = 0; i < rolls; i++)
            {
                result.AddRoll(RollD6());
            }

            return result;
        }


        public Distribution RollD3(Int32 rolls = 1)
        {
            Distribution result = new Distribution();

            for (int i = 0; i < rolls; i++)
            {
                result.AddRoll(RollD3());
            }

            return result;
        }


        private UInt16 RollD6()
        {
            double rand = randomNumberGenerator.NextDouble();

            // Map to 1-6

            return (UInt16)Math.Min(Math.Floor((rand * 6 * (1 + luckmodifier)))+1,6);
        }

        UInt16 RollD3()
        {
            double rand = randomNumberGenerator.NextDouble();

            // Map to 1-3

            return (UInt16)Math.Min(Math.Floor((rand * 3 * (1 + luckmodifier))) + 1, 3);
        }

        UInt16 Roll2D6()
        {
            UInt16 roll1 = RollD6();
            UInt16 roll2 = RollD6();

            return (UInt16)(roll1 + roll2);
        }
    }
}
